Behind the Scenes

Tom Elliott

satRdays Auckland 2020

Part I

What is iNZight, and who uses it?

library(iNZight)
iNZight()

iNZight main window

  • package
  • GUI for visually exploring data
  • easy-to-learn tool for students/beginners …
  • … but also non-beginners!

  • package
  • GUI for visually exploring data
  • easy-to-learn tool for students/beginners …
  • … but also non-beginners!
  • bridge between GUI and coding

Data

GUI

Explore

Save script

Part II

The development of iNZight

Another child of the University of Auckland

  • Chris Wild
  • Statistics students

How does it work?

gWidgets2 + gWidgets2RGtk2 RGtk2 GTK

† John Verzani ‡ Michael Lawrence

Started off small

  • a feature here …
  • a module there …

… et voilà: a rewrite was needed!

  • Object Oriented Programming (OOP)
  • Separability
  • Reactivity
  • Extensibility

Object Oriented Programming

  • reference classes
  • each component of the UI is represented by a class
  • classes have properties (“fields”) and methods
LoadDataWindow <- setRefClass("LoadDataWindow",
    fields = list(
        filename = "character"
    ),
    methods = list(
        initialize = function(...) {
            w <- gwindow("Load data")
            g <- ggroup(horizontal = FALSE, container = w)

            # Get filename from user
            fileedit <- gedit(container = g)

            # Load data
            loadbtn <- gbutton("Load", container = g)

            addHandlerKeystroke(fileedit,
                handler = function(h, ...) {
                    filename <<- svalue(h$obj)
                }
            )

            addHandlerClicked(loadbtn, function(h, ...) loadData())
        },
        loadData = function() {
            data <- read.csv(filename)
        }
    )
)

iNZight main window

Separability

  • keep UI and data logic separate
  • UI inputs control arguments to a single function
  • existing or new wrapper for another package
LoadDataWindow <- setRefClass("LoadDataWindow",
    fields = list(
        filename = "character"
    ),
    methods = list(
        initialize = function() { ... },
        loadData = function() {
            data <- read.csv(filename)
        }
    )
)
LoadDataWindow <- setRefClass("LoadDataWindow",
    fields = list(
        filename = "character",
        filetype = "character",
        delimiter = "character", # csv can use , or ;
        ...
    ),
    methods = list(
        initialize = function(...),
        loadData = function() {
            if (filetype == "csv") {
                data <- read.csv(filename, delimiter = delimiter, ...)
            } else if (filetype == "excel") {
                data <- readxl::read_xls(filename, ...)
            } else ...
        }
    )
)
LoadDataWindow <- setRefClass("LoadDataWindow",
    fields = list(
        filename = "character",
        filetype = "character",
        delimiter = "character", # csv can use , or ;
        ...
    ),
    methods = list(
        initialize(...),
        loadData = function() {
            data <- iNZightTools::smart_read(filename,
                filetype = filetype,
                delim = delimiter,
                ...
            )
        }
    )
)

Reactivity